home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 426-450 / disk_436 / keymacro / keymacro-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  19KB  |  952 lines

  1. /****************************************************************************
  2. *
  3. *    KeyMacro-Handler.c ----    KeyMacro handler.
  4. *
  5. *    Author ----------------    Olaf Barthel, MXM
  6. *                Brabeckstrasse 35
  7. *                D-3000 Hannover 71
  8. *
  9. *    KeyMacro  ©  Copyright  1990  by  MXM;  Executable  program,
  10. *    documentation  and  source  code are shareware.  If you like
  11. *    this  program  a  small donation will entitle you to receive
  12. *    updates and new programs from MXM.
  13. *
  14. ****************************************************************************/
  15.  
  16.     /* Function prototypes. */
  17.  
  18. struct Process *    CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize);
  19. VOID            FreeString(BPTR Byte);
  20. BPTR            CreateBSTR(char *s);
  21. BPTR            CopyPath(VOID);
  22. VOID            FakeCLI(VOID);
  23. VOID            ClearPath(BPTR InitPath);
  24. VOID            StopFakery(VOID);
  25. VOID *            DeleteMacroMsg(struct MacroMessage *scm_Msg);
  26. VOID            Executor(VOID);
  27. struct MacroKey *    FindMacroKey(LONG Code,LONG Qualifier);
  28. struct InputEvent *    EventHandler(struct InputEvent *Event);
  29. BYTE            OpenAll(VOID);
  30. VOID            CloseAll(VOID);
  31. BYTE            UStrCmp(UBYTE *a,UBYTE *b);
  32.  
  33. VOID *            AllocRem(LONG ByteSize,LONG Requirements);
  34. VOID *            FreeRem(LONG *MemoryBlock);
  35. VOID *            SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port);
  36. ULONG            KeyInvert(UBYTE AnsiKey,struct InputEvent *Event,struct KeyMap *KeyMap);
  37.  
  38. LONG            _main(VOID);
  39.  
  40.     /* The magic stuff. */
  41.  
  42. #pragma regcall(EventHandler(a0))
  43.  
  44.     /* Shared library identifiers. */
  45.  
  46. extern struct ExecBase    *SysBase;
  47. struct IntuitionBase    *IntuitionBase;
  48. struct Library        *LayersBase;
  49.  
  50.     /* Global handshake data. */
  51.  
  52. struct MSeg        *MSeg;
  53.  
  54.     /* Process<->Process communication data. */
  55.  
  56. struct Process        *ExecuteProc;
  57. struct MsgPort        *ExecutePort;
  58.  
  59.     /* Input device data. */
  60.  
  61. struct MsgPort        *InputDevPort;
  62. struct IOStdReq        *InputRequestBlock;
  63. struct Interrupt    *InputHandler;
  64. struct InputEvent    *FakeInputEvent;
  65.  
  66.     /* Console device data. */
  67.  
  68. struct IOStdReq        *ConsoleRequest;
  69. struct MsgPort        *ConsolePort;
  70.  
  71.     /* Timer device data. */
  72.  
  73. struct timerequest    *TimeRequest;
  74. struct MsgPort        *TimePort;
  75.  
  76. BYTE             SigBit = -1;
  77.  
  78.     /* Our current version tag. */
  79.  
  80. const char *VersionTag = "\0$VER: KeyMacro-Handler 1.8 (1 Dec 1990)\n\r";
  81.  
  82.     /* _main():
  83.      *
  84.      *    This is the entry point to the handler process.
  85.      */
  86.  
  87. LONG
  88. _main()
  89. {
  90.     struct Process        *ThatsMe;
  91.     ULONG             SignalSet;
  92.     struct MacroMessage    *MacroMsg;
  93.     LONG             i;
  94.  
  95.         /* Do I know myself? */
  96.  
  97.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  98.  
  99.         /* Don't let anybody call us from CLI. */
  100.  
  101.     if(ThatsMe -> pr_CLI)
  102.         goto Quit;
  103.  
  104.         /* Can we find the global MsgPort? */
  105.  
  106.     if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
  107.     {
  108.         Forbid();
  109.  
  110.         Signal(MSeg -> Father,MSeg -> RingBack);
  111.  
  112.         goto Quit;
  113.     }
  114.  
  115.         /* This older revision probably doesn't support
  116.          * some newer structure tags -> exit.
  117.          */
  118.  
  119.     if(MSeg -> Revision < REVISION)
  120.     {
  121.         Forbid();
  122.  
  123.         Signal(MSeg -> Father,MSeg -> RingBack);
  124.  
  125.         goto Quit;
  126.     }
  127.  
  128.         /* The MsgPort is already owned by someone
  129.          * else.
  130.          */
  131.  
  132.     if(MSeg -> Port . mp_Flags & PA_SIGNAL)
  133.     {
  134.         Forbid();
  135.  
  136.         Signal(MSeg -> Father,MSeg -> RingBack);
  137.  
  138.         goto Quit;
  139.     }
  140.  
  141.         /* Open the libraries. */
  142.  
  143.     if(!OpenAll())
  144.     {
  145.         CloseAll();
  146.  
  147.         Forbid();
  148.  
  149.         Signal(MSeg -> Father,MSeg -> RingBack);
  150.  
  151.         goto Quit;
  152.     }
  153.  
  154.         /* Start the executing process. */
  155.  
  156.     MSeg -> Child = (struct Task *)ThatsMe;
  157.  
  158.     if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro CLI",10,Executor,4000)))
  159.     {
  160.         CloseAll();
  161.  
  162.         Forbid();
  163.  
  164.         MSeg -> Child = NULL;
  165.         Signal(MSeg -> Father,MSeg -> RingBack);
  166.  
  167.         goto Quit;
  168.     }
  169.  
  170.         /* Wait for handshake signal. */
  171.  
  172.     Wait(SIG_SHAKE);
  173.  
  174.         /* Process creation failed. */
  175.  
  176.     if(!ExecuteProc)
  177.     {
  178.         CloseAll();
  179.  
  180.         Forbid();
  181.  
  182.         MSeg -> Child = NULL;
  183.         Signal(MSeg -> Father,MSeg -> RingBack);
  184.  
  185.         goto Quit;
  186.     }
  187.  
  188.         /* Now we are truly running. */
  189.  
  190.     Signal(MSeg -> Father,MSeg -> RingBack);
  191.  
  192.     MSeg -> Father = NULL;
  193.  
  194.         /* Re-init the MsgPort flags. */
  195.  
  196.     MSeg -> Port . mp_Flags        = PA_SIGNAL;
  197.     MSeg -> Port . mp_SigBit    = SigBit;
  198.     MSeg -> Port . mp_SigTask    = MSeg -> Child;
  199.  
  200.         /* Wait until somebody kicks us out. */
  201.  
  202.     FOREVER
  203.     {
  204.         SignalSet = Wait(SIG_CLOSE | SIG_PORT);
  205.  
  206.             /* We are to shut down. */
  207.  
  208.         if(SignalSet & SIG_CLOSE)
  209.         {
  210.             if(ExecuteProc)
  211.             {
  212.                 Signal((struct Task *)ExecuteProc,SIG_CLOSE);
  213.  
  214.                 Wait(SIG_SHAKE);
  215.             }
  216.  
  217.             CloseAll();
  218.  
  219.             Forbid();
  220.  
  221.             Signal(MSeg -> Father,SIG_CLOSE);
  222.  
  223.             goto Quit;
  224.         }
  225.  
  226.             /* A message arrived at our home port. */
  227.  
  228.         if(SignalSet & SIG_PORT)
  229.         {
  230.                 /* Walk through the list of messages. */
  231.  
  232.             while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
  233.             {
  234.                     /* Execute a keyboard macro. */
  235.  
  236.                 if(MacroMsg -> mm_Type == MM_INPUT)
  237.                 {
  238.                     struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
  239.  
  240.                     if(TempMacroKey)
  241.                     {
  242.                             /* Let the execute process run the command. */
  243.  
  244.                         if(TempMacroKey -> mk_Type == MK_COMMAND)
  245.                         {
  246.                             struct MacroMessage CommandMsg;
  247.  
  248.                             CommandMsg . mm_Type        = MM_EXECUTE;
  249.  
  250.                             CommandMsg . mm_FileName    = TempMacroKey -> mk_String;
  251.                             CommandMsg . mm_WindowName    = TempMacroKey -> mk_Window;
  252.  
  253.                             SendMacroMsg(&CommandMsg,ExecutePort);
  254.                         }
  255.  
  256.                             /* Build a keyboard macro. */
  257.  
  258.                         if(TempMacroKey -> mk_Type == MK_WORD)
  259.                         {
  260.                             ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  261.                             ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  262.                             ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  263.                             ConsoleRequest -> io_Flags    = IOF_QUICK;
  264.  
  265.                             DoIO(ConsoleRequest);
  266.  
  267.                             InputRequestBlock -> io_Command    = IND_WRITEEVENT;
  268.                             InputRequestBlock -> io_Data    = (APTR)FakeInputEvent;
  269.                             InputRequestBlock -> io_Length    = sizeof(struct InputEvent);
  270.  
  271.                             for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
  272.                             {
  273.                                 if(KeyInvert(TempMacroKey -> mk_String[i],FakeInputEvent,MSeg -> DefaultKeyMap))
  274.                                 {
  275.                                     FakeInputEvent -> ie_NextEvent    = NULL;
  276.                                     FakeInputEvent -> ie_Class    = IECLASS_RAWKEY;
  277.                                     FakeInputEvent -> ie_SubClass    = KM_SUBCLASS;
  278.  
  279.                                     FakeInputEvent -> ie_Qualifier |= IEQUALIFIER_RELATIVEMOUSE;
  280.  
  281.                                     TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  282.  
  283.                                     DoIO(TimeRequest);
  284.  
  285.                                     FakeInputEvent -> ie_TimeStamp = TimeRequest -> tr_time;
  286.  
  287.                                     DoIO(InputRequestBlock);
  288.  
  289.                                     if(MSeg -> Delay)
  290.                                     {
  291.                                         TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  292.                                         TimeRequest -> tr_time . tv_secs    = 0;
  293.                                         TimeRequest -> tr_time . tv_micro    = MSeg -> Delay;
  294.  
  295.                                         DoIO(TimeRequest);
  296.                                     }
  297.                                 }
  298.                             }
  299.                         }
  300.                     }
  301.                 }
  302.  
  303.                     /* This is a request to update the
  304.                      * macro keys.
  305.                      */
  306.  
  307.                 if(MacroMsg -> mm_Type == MM_UPDATE)
  308.                 {
  309.                     if(MSeg -> MacroList)
  310.                     {
  311.                         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  312.                         {
  313.                             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  314.                                 continue;
  315.  
  316.                             if(MSeg -> MacroList[i] . mk_String)
  317.                                 FreeRem(MSeg -> MacroList[i] . mk_String);
  318.  
  319.                             if(MSeg -> MacroList[i] . mk_Window)
  320.                                 FreeRem(MSeg -> MacroList[i] . mk_Window);
  321.                         }
  322.  
  323.                         FreeRem(MSeg -> MacroList);
  324.                     }
  325.  
  326.                     MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
  327.                     MSeg -> MacroList = MacroMsg -> mm_MacroList;
  328.                 }
  329.  
  330.                     /* Remove the message. */
  331.  
  332.                 DeleteMacroMsg(MacroMsg);
  333.             }
  334.         }
  335.     }
  336.  
  337. Quit:    ;
  338. }
  339.  
  340.     /* UStrCmp():
  341.      *
  342.      *    strcmp function which ignores case and allows to
  343.      *    abbreviate the name of the source string to match
  344.      *    against the destination string.
  345.      */
  346.  
  347. BYTE
  348. UStrCmp(UBYTE *a,UBYTE *b)
  349. {
  350.     SHORT i;
  351.  
  352.     for(i = 0 ; i < strlen(a) ; i++)
  353.         if(ToUpper(a[i]) != ToUpper(b[i]))
  354.             return(1);
  355.  
  356.     return(0);
  357. }
  358.  
  359.     /* CreateFuncProc():
  360.      *
  361.      *    Create an independent process from a 'C' routine.
  362.      */
  363.  
  364. struct Process *
  365. CreateFuncProc(char *Name,LONG Priority,APTR InitCode,ULONG StackSize)
  366. {
  367.     struct Process *ChildProc = NULL;
  368.  
  369.     struct FakeSeg
  370.     {
  371.         BPTR    NextSeg;
  372.  
  373.         WORD    FirstCode;
  374.         APTR    RealCode;
  375.     } *FakeSeg;
  376.  
  377.     if(FakeSeg = (struct FakeSeg *)AllocMem(sizeof(struct FakeSeg),MEMF_PUBLIC | MEMF_CLEAR))
  378.     {
  379.         struct MsgPort *ChildPort;
  380.  
  381.         FakeSeg -> FirstCode    = 0x4EF9;
  382.         FakeSeg -> RealCode    = InitCode;
  383.  
  384.         if(ChildPort = (struct MsgPort *)CreateProc(Name,Priority,MKBADDR(FakeSeg),StackSize))
  385.             ChildProc = (struct Process *)ChildPort -> mp_SigTask;
  386.  
  387.         Delay(TICKS_PER_SECOND);
  388.  
  389.         FreeMem(FakeSeg,sizeof(struct FakeSeg));
  390.     }
  391.  
  392.     return(ChildProc);
  393. }
  394.  
  395.     /* FreeString(Byte):
  396.      *
  397.      *    Frees the memory occupied by the contents of a BSTR.
  398.      */
  399.  
  400. VOID
  401. FreeString(BPTR Byte)
  402. {
  403.     LONG *Ptr = (LONG *)BADDR(Byte);
  404.  
  405.     FreeMem(Ptr - 1,Ptr[-1]);
  406. }
  407.  
  408.     /* CreateBSTR(s):
  409.      *
  410.      *    Allocates enough memory to hold the contents of
  411.      *    a given string and makes it a BSTR.
  412.      */
  413.  
  414. BPTR
  415. CreateBSTR(char *s)
  416. {
  417.     LONG     BlockLength;
  418.     SHORT     Length;
  419.     char    *Byte;
  420.  
  421.     Length = strlen(s);
  422.  
  423.     BlockLength = (Length + 8) & ~3;
  424.  
  425.     if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
  426.         return(NULL);
  427.  
  428.     *(LONG *)Byte = BlockLength;
  429.  
  430.     Byte[4] = Length;
  431.     strncpy(Byte + 5,s,Length);
  432.  
  433.     return(MKBADDR(Byte + 4));
  434. }
  435.  
  436.     /* CopyPath():
  437.      *
  438.      *    Builds a fake pathlist inherited from any valid
  439.      *    CLI process or Workbench.
  440.      */
  441.  
  442. BPTR
  443. CopyPath()
  444. {
  445.     BPTR                *Next1,*Next2,*Last,NewPath = NULL;
  446.     struct Process            *Father;
  447.     struct CommandLineInterface    *CLI;
  448.  
  449.     Last = &NewPath;
  450.  
  451.         /* If using ARP this will also give us a valid
  452.          * pathlist.
  453.          */
  454.  
  455.     if(!(Father = (struct Process *)FindTask("Workbench")))
  456.         if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
  457.             if(!(Father = (struct Process *)FindTask("New CLI")))
  458.                 if(!(Father = (struct Process *)FindTask("Initial CLI")))
  459.                     return(NULL);
  460.  
  461.     if(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI))
  462.     {
  463.         for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
  464.         {
  465.             if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
  466.                 break;
  467.  
  468.             *Last = MKBADDR(Next2);
  469.              Last = Next2;
  470.  
  471.             Next2[1] = (BPTR)DupLock(Next1[1]);
  472.             Next2[0] = NULL;
  473.         }
  474.     }
  475.  
  476.     return(NewPath);
  477. }
  478.  
  479.     /* FakeCLI():
  480.      *
  481.      *    Creates a fake CLI structure for our process. This
  482.      *    includes pathlist, currentdir, prompt and stack.
  483.      */
  484.  
  485. VOID
  486. FakeCLI()
  487. {
  488.     struct Process            *MyProcess = (struct Process *)SysBase -> ThisTask;
  489.     struct CommandLineInterface    *CLI;
  490.  
  491.     if(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR))
  492.     {
  493.         MyProcess -> pr_CLI = MKBADDR(CLI);
  494.  
  495.         CLI -> cli_SetName    = CreateBSTR("SYS:");
  496.         CLI -> cli_Prompt    = CreateBSTR("%N> ");
  497.         CLI -> cli_DefaultStack    = 4000;
  498.  
  499.         CurrentDir(Lock("SYS:",ACCESS_READ));
  500.  
  501.         CLI -> cli_CommandDir    = CopyPath();
  502.     }
  503. }
  504.  
  505.     /* ClearPath(InitPath):
  506.      *
  507.      *    Frees the contents of our fake pathlist.
  508.      */
  509.  
  510. VOID
  511. ClearPath(BPTR InitPath)
  512. {
  513.     BPTR *Next,*Path;
  514.  
  515.     for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
  516.     {
  517.         Next = (BPTR *)BADDR(Path[0]);
  518.  
  519.         if(Path[1])
  520.             UnLock(Path[1]);
  521.  
  522.         FreeMem(Path,2 * sizeof(BPTR));
  523.     }
  524. }
  525.  
  526.     /* StopFakery():
  527.      *
  528.      *    Removes the contents of our fake CLI structure.
  529.      */
  530.  
  531. VOID
  532. StopFakery()
  533. {
  534.     struct CommandLineInterface    *CLI;
  535.     struct Process            *MyProcess;
  536.     BPTR                 MyCD;
  537.  
  538.     MyProcess = (struct Process *)SysBase -> ThisTask;
  539.  
  540.     if(CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI))
  541.     {
  542.         if(MyCD = (BPTR)CurrentDir(NULL))
  543.             UnLock(MyCD);
  544.  
  545.         FreeString(CLI -> cli_SetName);
  546.         FreeString(CLI -> cli_Prompt);
  547.  
  548.         ClearPath(CLI -> cli_CommandDir);
  549.  
  550.         MyProcess -> pr_CLI = NULL;
  551.  
  552.         FreeMem(CLI,sizeof(struct CommandLineInterface));
  553.     }
  554. }
  555.  
  556.     /* DeleteMacroMsg(scm_Msg):
  557.      *
  558.      *    Remove a message from memory.
  559.      */
  560.  
  561. VOID *
  562. DeleteMacroMsg(struct MacroMessage *scm_Msg)
  563. {
  564.     if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (char *)scm_Msg)
  565.         FreeRem(scm_Msg);
  566.  
  567.     return(NULL);
  568. }
  569.  
  570.     /* Executor():
  571.      *
  572.      *    This is the dummy process to execute programs.
  573.      */
  574.  
  575. VOID
  576. Executor()
  577. {
  578.     ULONG             SignalSet;
  579.     BPTR             NIL;
  580.     struct MacroMessage    *ExecuteMsg;
  581.     struct Window        *TheWindow;
  582.     char             TempLine[300];
  583.  
  584.     struct Process        *ThatsMe;
  585.  
  586.     BYTE             Activate;
  587.  
  588.     geta4();
  589.  
  590.     ThatsMe = (struct Process *)SysBase -> ThisTask;
  591.  
  592.         /* These are inherited from the father process,
  593.          * we had better cleared them out.
  594.          */
  595.  
  596.     ThatsMe -> pr_WindowPtr = (APTR)-1;
  597.  
  598.         /* Try to allocate a port (we can't use our builtin
  599.          * DOS port since we are actually calling DOS
  600.          * routines which may mix up the messages coming
  601.          * in).
  602.          */
  603.  
  604.     if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
  605.     {
  606.         Forbid();
  607.  
  608.         ExecuteProc = NULL;
  609.  
  610.         Signal(MSeg -> Child,SIG_SHAKE);
  611.  
  612.         goto Quit;
  613.     }
  614.  
  615.         /* Open the NULL-Handler. */
  616.  
  617.     if(!(NIL = Open("NULL:",MODE_NEWFILE)))
  618.     {
  619.         Forbid();
  620.  
  621.         ExecuteProc = NULL;
  622.  
  623.         Signal(MSeg -> Child,SIG_SHAKE);
  624.         DeletePort(ExecutePort);
  625.  
  626.         goto Quit;
  627.     }
  628.  
  629.         /* Pretend to be a CLI. */
  630.  
  631.     FakeCLI();
  632.  
  633.         /* This path leads nowhere. */
  634.  
  635.     ThatsMe -> pr_CIS        = NIL;
  636.     ThatsMe -> pr_COS        = NIL;
  637.  
  638.     ThatsMe -> pr_ConsoleTask    = (APTR)DeviceProc("NULL:");
  639.  
  640.         /* We're on the scene now. */
  641.  
  642.     Signal(MSeg -> Child,SIG_SHAKE);
  643.  
  644.     FOREVER
  645.     {
  646.         SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
  647.  
  648.             /* Shut down? */
  649.  
  650.         if(SignalSet & SIG_CLOSE)
  651.         {
  652.             StopFakery();
  653.             Close(NIL);
  654.             DeletePort(ExecutePort);
  655.  
  656.             ExecuteProc = NULL;
  657.  
  658.             Forbid();
  659.  
  660.             Signal(MSeg -> Child,SIG_SHAKE);
  661.  
  662.             goto Quit;
  663.         }
  664.  
  665.             /* Execute a command? */
  666.  
  667.         while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
  668.         {
  669.             TheWindow    = NULL;
  670.             Activate    = TRUE;
  671.  
  672.                 /* Try to find a matching window title. */
  673.  
  674.             if(ExecuteMsg -> mm_WindowName)
  675.             {
  676.                 ULONG         IntuiLock;
  677.  
  678.                 struct Screen    *ExScreen;
  679.                 struct Window    *ExWindow;
  680.  
  681.                 IntuiLock = LockIBase(NULL);
  682.  
  683.                 if(UStrCmp(ExecuteMsg -> mm_WindowName,IntuitionBase -> ActiveWindow -> Title))
  684.                 {
  685.                     ExScreen = IntuitionBase -> FirstScreen;
  686.  
  687.                     do
  688.                     {
  689.                         ExWindow = ExScreen -> FirstWindow;
  690.  
  691.                         do
  692.                         {
  693.                             if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
  694.                             {
  695.                                 TheWindow = ExWindow;
  696.                                 break;
  697.                             }
  698.                         }
  699.                         while((ExWindow = ExWindow -> NextWindow) && !TheWindow);
  700.                     }
  701.                     while((ExScreen = ExScreen -> NextScreen) && !TheWindow);
  702.                 }
  703.                 else
  704.                 {
  705.                     TheWindow = IntuitionBase -> ActiveWindow;
  706.                     Activate = FALSE;
  707.                 }
  708.  
  709.                 UnlockIBase(IntuiLock);
  710.             }
  711.  
  712.             if(!TheWindow)
  713.             {
  714.                     /* No chance, execute the command. */
  715.  
  716.                 strcpy(TempLine,"C:Run <NULL: >NULL: ");
  717.                 strcat(TempLine,ExecuteMsg -> mm_FileName);
  718.  
  719.                 Execute(TempLine,NULL,NIL);
  720.             }
  721.  
  722.             DeleteMacroMsg(ExecuteMsg);
  723.  
  724.                 /* Found a window? Bring it to the front. */
  725.  
  726.             if(TheWindow)
  727.             {
  728.                 LockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  729.  
  730.                 WindowToFront(TheWindow);
  731.  
  732.                 UnlockLayers(TheWindow -> RPort -> Layer -> LayerInfo);
  733.  
  734.                 ScreenToFront(TheWindow -> WScreen);
  735.  
  736.                 if(Activate)
  737.                     ActivateWindow(TheWindow);
  738.             }
  739.         }
  740.     }
  741.  
  742.         /* Finished, fall through. */
  743.  
  744. Quit:    ;
  745. }
  746.  
  747.     /* FindMacroKey(Code,Qualifier):
  748.      *
  749.      *    Find a macro key entry in the linked list of
  750.      *    macro key structures.
  751.      */
  752.  
  753. struct MacroKey *
  754. FindMacroKey(LONG Code,LONG Qualifier)
  755. {
  756.     SHORT i;
  757.  
  758.     if(MSeg -> MacroList)
  759.     {
  760.         for(i = 0 ; i < MSeg -> NumMacros ; i++)
  761.         {
  762.             if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
  763.                 continue;
  764.  
  765.             if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
  766.                 return(&MSeg -> MacroList[i]);
  767.         }
  768.     }
  769.  
  770.     return(NULL);
  771. }
  772.  
  773.     /* EventHandler(Event):
  774.      *
  775.      *    The input event handler.
  776.      */
  777.  
  778. struct InputEvent *
  779. EventHandler(struct InputEvent *Event)
  780. {
  781.     struct MacroKey        *HandlerKey;
  782.     struct InputEvent    *ChainEvent;
  783.  
  784.         /* This is an interrupt, let's start with the register
  785.          * saving.
  786.          */
  787.  
  788.     int_start();
  789.  
  790.     for(ChainEvent = Event ; ChainEvent ; ChainEvent = ChainEvent -> ie_NextEvent)
  791.     {
  792.         if(ChainEvent -> ie_Class == IECLASS_RAWKEY && !(ChainEvent -> ie_Code & IECODE_UP_PREFIX) && ChainEvent -> ie_SubClass != KM_SUBCLASS)
  793.         {
  794.             if(HandlerKey = (struct MacroKey *)FindMacroKey(ChainEvent -> ie_Code,ChainEvent -> ie_Qualifier))
  795.             {
  796.                 struct MacroMessage HandlerMsg;
  797.  
  798.                 HandlerMsg . mm_Type        = MM_INPUT;
  799.                 HandlerMsg . mm_MacroKey    = HandlerKey;
  800.  
  801.                 SendMacroMsg(&HandlerMsg,&MSeg -> Port);
  802.  
  803.                 ChainEvent -> ie_Class = IECLASS_NULL;
  804.             }
  805.         }
  806.     }
  807.  
  808.         /* Restore the registers. */
  809.  
  810.     int_end();
  811.  
  812.     return(Event);
  813. }
  814.  
  815.     /* OpenAll():
  816.      *
  817.      *    Initialize the input event handler.
  818.      */
  819.  
  820. BYTE
  821. OpenAll()
  822. {
  823.     if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",33)))
  824.         return(FALSE);
  825.  
  826.     if(!(LayersBase = (struct Library *)OpenLibrary("layers.library",33)))
  827.         return(FALSE);
  828.  
  829.     if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
  830.         return(FALSE);
  831.  
  832.     if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
  833.         return(FALSE);
  834.  
  835.     if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
  836.         return(FALSE);
  837.  
  838.     if(!(InputHandler = (struct Interrupt *)AllocMem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
  839.         return(FALSE);
  840.  
  841.     if(!(ConsolePort = (struct MsgPort *)CreatePort(NULL,0)))
  842.         return(FALSE);
  843.  
  844.     if(!(ConsoleRequest = (struct IOStdReq *)CreateStdIO(ConsolePort)))
  845.         return(FALSE);
  846.  
  847.     if(OpenDevice("console.device",CONU_LIBRARY,ConsoleRequest,0))
  848.         return(FALSE);
  849.  
  850.     if(!(TimePort = (struct MsgPort *)CreatePort(NULL,0)))
  851.         return(FALSE);
  852.  
  853.     if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest))))
  854.         return(FALSE);
  855.  
  856.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  857.         return(FALSE);
  858.  
  859.     if(!(FakeInputEvent = (struct InputEvent *)AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC | MEMF_CLEAR)))
  860.         return(FALSE);
  861.  
  862.     if((SigBit = AllocSignal(-1)) == -1)
  863.         return(FALSE);
  864.  
  865.     InputHandler -> is_Code            = (APTR)EventHandler;
  866.     InputHandler -> is_Node . ln_Pri    = 51;
  867.     InputHandler -> is_Node . ln_Name    = "KeyMacro-Handler";
  868.  
  869.     InputRequestBlock -> io_Command        = IND_ADDHANDLER;
  870.     InputRequestBlock -> io_Data        = (APTR)InputHandler;
  871.  
  872.     if(DoIO(InputRequestBlock))
  873.         return(FALSE);
  874.  
  875.     ConsoleRequest -> io_Command    = CD_ASKDEFAULTKEYMAP;
  876.     ConsoleRequest -> io_Length    = sizeof(struct KeyMap);
  877.     ConsoleRequest -> io_Data    = (APTR)MSeg -> DefaultKeyMap;
  878.     ConsoleRequest -> io_Flags    = IOF_QUICK;
  879.  
  880.     if(DoIO(ConsoleRequest))
  881.         return(FALSE);
  882.  
  883.     return(TRUE);
  884. }
  885.  
  886.     /* CloseAll():
  887.      *
  888.      *    Remove the input event handler.
  889.      */
  890.  
  891. VOID
  892. CloseAll()
  893. {
  894.     if(InputRequestBlock)
  895.     {
  896.         if(InputRequestBlock -> io_Device)
  897.         {
  898.             if(InputHandler)
  899.             {
  900.                 InputRequestBlock -> io_Command    = IND_REMHANDLER;
  901.                 InputRequestBlock -> io_Data    = (APTR)InputHandler;
  902.  
  903.                 DoIO(InputRequestBlock);
  904.             }
  905.  
  906.             CloseDevice(InputRequestBlock);
  907.         }
  908.  
  909.         DeleteStdIO(InputRequestBlock);
  910.     }
  911.  
  912.     if(TimeRequest)
  913.     {
  914.         if(TimeRequest -> tr_node . io_Device)
  915.             CloseDevice(TimeRequest);
  916.  
  917.         DeleteExtIO(TimeRequest);
  918.     }
  919.  
  920.     if(TimePort)
  921.         DeletePort(TimePort);
  922.  
  923.     if(ConsoleRequest)
  924.     {
  925.         if(ConsoleRequest -> io_Device)
  926.             CloseDevice(ConsoleRequest);
  927.  
  928.         DeleteStdIO(ConsoleRequest);
  929.     }
  930.  
  931.     if(FakeInputEvent)
  932.         FreeMem(FakeInputEvent,sizeof(struct InputEvent));
  933.  
  934.     if(InputHandler)
  935.         FreeMem(InputHandler,sizeof(struct Interrupt));
  936.  
  937.     if(InputDevPort)
  938.         DeletePort(InputDevPort);
  939.  
  940.     if(ConsolePort)
  941.         DeletePort(ConsolePort);
  942.  
  943.     if(SigBit != -1)
  944.         FreeSignal(SigBit);
  945.  
  946.     if(LayersBase)
  947.         CloseLibrary(LayersBase);
  948.  
  949.     if(IntuitionBase)
  950.         CloseLibrary(IntuitionBase);
  951. }
  952.